import sys
from pathlib import Path

import gradio as gr

sys.path.append(str(Path(__file__).parent.parent))
import base64
import time
from typing import Dict, List, Tuple

import cv2
import numpy as np
import requests

from configs.global_config import global_config

global_config.initialize()
print(global_config.raw_config)

# 配置API端点
API_BASE_URL = f"http://{global_config.get('server.host', 'localhost')}:{global_config.get('server.port', 5555)}"


def check_api_status() -> bool:
    """检查API服务状态"""
    try:
        response = requests.post(
            f"{API_BASE_URL}/extract_face_features",
            json={"image_base64": "test"},
            timeout=3,
        )
        # 400表示服务存在但参数错误，405表示方法不允许
        return response.status_code in (400, 405)
    except:  # noqa: E722
        return False


def extract_single_face(image: np.ndarray) -> Tuple[Dict, np.ndarray]:
    """处理单张图片"""
    if not check_api_status():
        return {"error": "API服务不可用"}, None

    try:
        _, buffer = cv2.imencode(".jpg", image)
        img_base64 = base64.b64encode(buffer).decode("utf-8")

        start_time = time.time()
        response = requests.post(
            f"{API_BASE_URL}/extract_face_features",
            json={"image_base64": img_base64},
            timeout=30,
        )
        processing_time = time.time() - start_time

        result = response.json()
        if response.status_code != 200:
            return result, None

        # 绘制检测框
        output_img = image.copy()
        for face in result.get("data", []):
            bbox = face.get("bbox", [])
            if len(bbox) == 4:
                cv2.rectangle(
                    output_img,
                    (int(bbox[0]), int(bbox[1])),
                    (int(bbox[2]), int(bbox[3])),
                    (0, 255, 0),
                    2,
                )

        result["processing_time"] = f"{processing_time:.2f}s"
        return result, output_img

    except Exception as e:
        return {"error": f"处理失败: {str(e)}"}, None


def extract_batch_face(images: List[np.ndarray]) -> Tuple[Dict, List[np.ndarray]]:
    """批量处理图片"""
    if not check_api_status():
        return {"error": "API服务不可用"}, []

    try:
        batch_data = []
        for idx, img in enumerate(images):
            try:
                _, buffer = cv2.imencode(".jpg", img)
                if buffer is None:
                    raise ValueError("图片编码失败")
                img_base64 = base64.b64encode(buffer).decode("utf-8")
                if not img_base64:
                    raise ValueError("base64编码失败")
                batch_data.append(
                    {"image_name": f"image_{idx}", "image_base64": img_base64}
                )
            except Exception as e:
                return {"error": f"图片{idx}处理失败: {str(e)}"}, []

        start_time = time.time()
        response = requests.post(
            f"{API_BASE_URL}/batch_extract_face_features",
            json={"images_base64": batch_data},
            timeout=60,
        )
        processing_time = time.time() - start_time

        result = response.json()
        if response.status_code != 200:
            return result, []

        # 处理结果图片
        output_images = []
        for img, res in zip(images, result.get("data", {}).get("results", [])):
            if res.get("success"):
                output_img = img.copy()
                for face in res.get("features", []):
                    bbox = face.get("bbox", [])
                    if len(bbox) == 4:
                        cv2.rectangle(
                            output_img,
                            (int(bbox[0]), int(bbox[1])),
                            (int(bbox[2]), int(bbox[3])),
                            (0, 255, 0),
                            2,
                        )
                output_images.append(output_img)

        result["processing_time"] = f"{processing_time:.2f}s"
        return result, output_images

    except Exception as e:
        return {"error": f"批量处理失败: {str(e)}"}, []


def create_face_feature_ui():
    """创建人脸特征提取UI"""
    with gr.Blocks():
        # API状态提示
        api_status = gr.HTML(
            value=f'<div style="color: {"green" if check_api_status() else "red"}">'
            f"API服务状态: {'可用' if check_api_status() else '不可用'}</div>"
        )

        with gr.Tabs():
            with gr.Tab("单张图片处理"):
                with gr.Row():
                    with gr.Column():
                        input_image = gr.Image(label="上传图片", type="numpy")
                        with gr.Row():
                            extract_btn = gr.Button("提取特征", variant="primary")
                            clear_btn = gr.Button("清空")
                    with gr.Column():
                        output_image = gr.Image(label="检测结果", interactive=False)
                        feature_output = gr.JSON(label="特征数据")

                with gr.Accordion("处理详情", open=False):
                    gr.Markdown("""
                    - 支持JPEG/PNG格式图片
                    - 最大尺寸: 4096x4096像素
                    - 单次处理时间约1-3秒
                    """)

            with gr.Tab("批量图片处理"):
                with gr.Row():
                    with gr.Column():
                        batch_input = gr.Gallery(label="上传多张图片")
                        with gr.Row():
                            batch_extract_btn = gr.Button("批量提取", variant="primary")
                            batch_clear_btn = gr.Button("清空")
                    with gr.Column():
                        batch_output = gr.Gallery(label="处理结果")
                        batch_feature_output = gr.JSON(label="批量特征数据")

                with gr.Accordion("批量处理说明", open=False):
                    gr.Markdown("""
                    - 最多支持同时处理10张图片
                    - 处理时间与图片数量成正比
                    - 结果按上传顺序排列
                    """)

        # 单图处理逻辑
        extract_btn.click(
            fn=extract_single_face,
            inputs=input_image,
            outputs=[feature_output, output_image],
        )

        clear_btn.click(fn=lambda: [None, None], outputs=[output_image, feature_output])

        # 批量处理逻辑
        batch_extract_btn.click(
            fn=extract_batch_face,
            inputs=batch_input,
            outputs=[batch_feature_output, batch_output],
        )

        batch_clear_btn.click(
            fn=lambda: [None, None], outputs=[batch_output, batch_feature_output]
        )
